package com.sentinel.client;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.sentinel.common.Result;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @author 谢阳
 * @version 1.0
 * @date 2023/11/21 14:22
 * @description
 */
@FeignClient(value = "user-demo",url = "localhost:8888",fallbackFactory = UserClientFallbackFactory.class)
@Component
public interface UserClient {

    @GetMapping("/user/{id}")
    Result getUserById(@PathVariable("id") Long id);
}

@Slf4j
@Component
class UserClientFallbackFactory implements FallbackFactory<UserClient> {
    @Override
    public UserClient create(Throwable throwable) {
        return new UserClient() {
            @Override
            public Result getUserById(Long id) {
                if (throwable instanceof BlockException) {
                    Result result = null;
                    if (throwable instanceof FlowException) {
                        result = Result.failure(100, "接口被限流了");
                    } else if (throwable instanceof DegradeException) {
                        result = Result.failure(101, "服务降级了");
                    } else if (throwable instanceof ParamFlowException) {
                        result = Result.failure(102, "热点参数限流了");
                    } else if (throwable instanceof AuthorityException) {
                        result = Result.failure(104, "授权规则不通过");
                    }
                    log.info("sentinel 异常 ===> [{}]", result);
                    return result;
                }
                log.info("远程调用异常 ====> [{}]", throwable.getMessage());
                return Result.failure("用户 [" + id + "] 远程调用异常");
            }
        };
    }
}
